const OSC_RESERVED_USER_NAMES = ["explore", "repositories", "popular", "enterprises", "gists", "dashboard", "languages", "search", "links", "invite", "profile", "organizations", "notifications", "login", "signup", "oauth"]
const OSC_RESERVED_REPO_NAMES = ["admin", "dashboard", "groups", "help", "profile", "projects", "search", "codes", "fork_project", "fork_code"]
const OSC_404_SEL = '#parallax_wrapper'
const OSC_PJAX_CONTAINER_SEL = '.blob-viewer'
const OSC_CONTAINERS = '.navbar .navbar-gitlab .navbar-gitlab-new .with-horizontal-nav'
const OSC_RAW_CONTENT = 'body > pre'
const RESULT = []
const TREE_DIR = []
const index = 0


class Gitlab extends PjaxAdapter {

  constructor(store) {
    super(store)
  }

  // @override
  init($sidebar) {
    const pjaxContainer = $(OSC_PJAX_CONTAINER_SEL)[0]
    super.init($sidebar, {'pjaxContainer': pjaxContainer})

    // Fix #151 by detecting when page layout is updated.
    // In this case, split-diff page has a wider layout, so need to recompute margin.
    // Note that couldn't do this in response to URL change, since new DOM via pjax might not be ready.
    const diffModeObserver = new window.MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (~mutation.oldValue.indexOf('split-diff') ||
          ~mutation.target.className.indexOf('split-diff')) {
          return $(document).trigger(EVENT.LAYOUT_CHANGE)
        }
      })
    })

    diffModeObserver.observe(document.body, {
      attributes: true,
      attributeFilter: ['class'],
      attributeOldValue: true
    })
  }

  // @override
  _getCssClass() {
    return 'octotree_oschina_sidebar'
  }

  // @override
  canLoadEntireTree() {
    return true
  }

  // @override
  getCreateTokenUrl() {
    return `https://gitee.com/api/v5/swagger`
  }

  // @override
  updateLayout(togglerVisible, sidebarVisible, sidebarWidth) {
    const SPACING = 232
    const $containers = $(OSC_CONTAINERS)
    const autoMarginLeft = ($(document).width() - $containers.width()) / 2
    const WIDTH = $(document).width() - SPACING
    const shouldPushLeft = sidebarVisible && (autoMarginLeft <= sidebarWidth + SPACING)

    $('html').css('margin-left', shouldPushLeft ? sidebarWidth : '')
    $containers.css('margin-left', shouldPushLeft ? SPACING : '')
    $containers.css('width', shouldPushLeft ? WIDTH : '')
    // $(".ui.right.floated.horizontal.list").css('margin-right', shouldPushLeft ? 210 : '')
    $(".git-project-download-panel").css('margin-right', shouldPushLeft ? 240 : '')
  }

  // @override
  getRepoFromPath(currentRepo, token, cb) {
    const showInNonCodePage = this.store.get(STORE.NONCODE)

    // 404 page, skip
    if ($(OSC_404_SEL).length) {
      return cb()
    }

    // Skip raw page
    if ($(OSC_RAW_CONTENT).length) {
      return cb()
    }

    // (username)/(reponame)[/(type)]
    const match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?/)
    if (!match) {
      return cb()
    }

    const username = match[1]
    const reponame = match[2]

    // Not a repository, skip
    if (~OSC_RESERVED_USER_NAMES.indexOf(username) ||
      ~OSC_RESERVED_REPO_NAMES.indexOf(reponame)) {
      return cb()
    }

    // Skip non-code page unless showInNonCodePage is true
    if (!showInNonCodePage && match[3] && !~['tree', 'blob'].indexOf(match[3])) {
      return cb()
    }

    // Get branch by inspecting page, quite fragile so provide multiple fallbacks
    const branch =
      // Code page
      $('.dropdown-toggle-text').text().trim() ||
      // Pull requests page
      ($('.commit-ref.base-ref').attr('title') || ':').match(/:(.*)/)[1] ||
      // Reuse last selected branch if exist
      (currentRepo.username === username && currentRepo.reponame === reponame && currentRepo.branch) ||
      // Get default branch from cache
      this._defaultBranch[username + '/' + reponame]

    // Still no luck, get default branch for real
    const repo = {username: username, reponame: reponame, branch: branch}

    if (repo.branch) {
      cb(null, repo)
    } else {
      this._getBranch(null, {repo, token}, (err, data) => {

        if (err) return cb(err)
        repo.branch = this._defaultBranch[username + '/' + reponame] = data.default_branch || 'master'
        cb(null, repo)
      })
    }
  }

  // @override
  selectFile(path) {

    var href = window.location.origin + path;

    //加载文件信息
    $.ajax({
      type: "GET",
      url: href,
      dataType: 'html',
      success: function (data) {
        var content = $(data).find(".content-wrapper").html();
        var title = data.substr(data.indexOf("<title>") + 7, data.indexOf("</title>") - data.indexOf("<title>") - 7)
        var stateObject = {};
        history.pushState(stateObject, title, href);
        $(document).attr("title", title);
        try {
          $(".content-wrapper").html(content);
        } catch (err) {
          //console.info(err);
        } finally {
          //加载内容
          $.ajax({
            type: "GET",
            url: href + '?format=json&viewer=simple',
            dataType: 'json',
            success: function (result) {
              $(".blob-viewer").replaceWith(result.html)
            }
          });
        }

      }
    })
  }

  // @override
  loadCodeTree(opts, cb) {
    if (opts.lazyPath === undefined) {
      // console.log(111)
      opts.encodedBranch = encodeURIComponent(decodeURIComponent(opts.repo.branch))
      opts.path = (opts.node && (opts.node.sha || opts.encodedBranch)) ||
        (opts.encodedBranch + '?recursive=1')
    }
    this._loadCodeTreeInternal(opts, null, cb)
  }

  // @override
  _getTree(path, opts, cb) {

    this._get(`${path}`, opts, (err, res) => {
      if (err) cb(err)
      else cb(null, res)
    })
  }

  // @override
  _getSubmodules(tree, opts, cb) {
    cb()
  }

  _get(path, opts, cb) {
// 重复路径判断

    var href = opts.lazyPath;
    // console.log(TREE_DIR)
    // console.log(href)
    if (this._isInArray(TREE_DIR, href)) {
      cb(null,RESULT)
      return
    } else {
      TREE_DIR.push(href);
      // console.log(TREE_DIR)
    }

    this.store.set("souche", opts)

    const host = location.protocol + '//' + location.host
    var project_id = $('#project_id').val() || $('#search_project_id').val();
    var url = ''
    if (opts.lazyPath === undefined) {
      url = `${host}/api/v4/projects/${project_id}/repository/tree?ref=${opts.repo.branch}&path=`
    } else {
      url = `${host}/api/v4/projects/${project_id}/repository/tree?path=${opts.lazyPath}`
    }

    // console.log(opts)
    // console.log(url)
    $.ajax({
      url,
      method: 'GET',
      cache: false,
      async: false,
      xhrFields: {
        withCredentials: true
      },
    })
      .done((data) => {
        // 递归目录树
        // this._checkTree(url, data)
        for (var i = 0; i < data.length; i++) {
          // console.log(data[i])
          RESULT.push(data[i])
        }
        // console.log(RESULT)
        cb(null, RESULT)
      })
  }


  _isInArray(arr, value) {
    // console.log(arr)

    for (var i = 0; i < arr.length; i++) {
      if (value === arr[i]) {
        return true;
      }
    }
    return false;
  }


  _checkTree(u, data) {
    for (var i = 0; i < data.length; i++) {
      // console.log(data[i])
      RESULT.push(data[i])
      if (data[i].type === 'tree') {
        var request = (retry) => {
          const url = u + data[i].path
          // console.log(url)
          const param = {
            url,
            method: 'GET',
            cache: false,
            async: false,
            xhrFields: {
              withCredentials: true
            },
          }
          $.ajax(param)
            .done((data) => {
              this._checkTree(u, data);
            })
        }
        request(true)
      }
    }
    return true;

  }


  _getBranch(path, opts, cb) {
    const host = location.protocol + '//' + location.host
    var project_id = $('#project_id').val() || $('#search_project_id').val();
    var url = `${host}/api/v4/projects/${project_id}/repository/tree?ref=${opts.branch}&path=`
    var request = (retry) => {
      if (!retry && opts.token) {
        url += (url.indexOf("?") >= 0 ? "&" : "?") + `access_token=${opts.token}`
      }
      const cfg = {
        url,
        method: 'GET',
        cache: false,
        async: false,
        xhrFields: {
          withCredentials: true
        },
      }
      $.ajax(cfg)
        .done((data) => {
          cb(null, data)
        })
        .fail((jqXHR) => {
          if (retry) {
            request(false)
          } else {
            this._handleError(jqXHR, cb)
          }
        })
    }
    request(true)
  }
}
